<template>
  <el-dialog
    v-model="dialogVisible"
    :destroy-on-close="true"
    width="50%"
    draggable
    show-close
    :title="ruleForm['id'] ? '修改字段' : '添加字段'"
  >
    <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="140px" :disabled="preview">
      <el-form-item label="code" prop="columnCode">
        <el-input v-model="ruleForm.columnCode" />
      </el-form-item>
      <el-form-item label="名称" prop="columnName">
        <el-input v-model="ruleForm.columnName" placeholder="为空，则和code相同" />
      </el-form-item>
      <el-form-item label="数据类型" prop="columnType">
        <el-select v-model="ruleForm.columnType" placeholder="数据类型">
          <el-option v-for="item in ColumnType" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>

      <el-form-item label="类型" prop="dimensionType">
        <el-cascader
          v-model="ruleForm.dimensionType"
          :options="ColumnDimensionTypes[ruleForm.columnType]"
          @change="dimensionTypeChange"
        />
      </el-form-item>
      <template v-if="!isFile && !isAgg && ruleForm.columnType != ColumnTypeEnum.date">
        <el-form-item
          label="枚举值"
          v-if="columnOptionsType == ColumnOptionsType.custom || columnOptionsType == ColumnOptionsType.null"
        >
          <el-form-item
            prop="columnOptions"
            style="width: 50%"
            :rules="[
              {
                pattern: /^(([\u4E00-\u9FA5A-Za-z0-9]+):([\u4E00-\u9FA5A-Za-z0-9]+)(,?))+$/,
                message: '格式要求: key:value,key:value'
              }
            ]"
          >
            <el-input v-model="ruleForm.columnOptions" placeholder="格式要求: key:value,key:value" clearable />
          </el-form-item>

          <el-col class="text-center" :span="1">
            <span class="text-gray-500"></span>
          </el-col>

          <el-form-item>
            <el-button
              :icon="Link"
              @click="
                columnOptionsType = ColumnOptionsType.link_table;
                ruleForm.defaultValue = '';
              "
              >关联表
            </el-button>
          </el-form-item>
        </el-form-item>

        <TableColumnForm
          ref="tableColumnFormRef"
          v-else
          :preview="preview"
          v-model:value-label="valueLabel"
          v-model:value-code="valueCode"
          v-model:table-info-id="tableInfoId"
          @column-options-type-change="
            columnOptionsType = ColumnOptionsType.custom;
            ruleForm.defaultValue = '';
          "
        ></TableColumnForm>
      </template>

      <el-form-item
        label="默认值"
        prop="defaultValue"
        v-if="!isAgg && ruleForm.dimensionType[1] != DimensionExtraEnum.dimension_primary_key"
      >
        <UploadImg
          v-if="isFile"
          :file-size="3"
          :file-type="
            ruleForm.dimensionExtra == DimensionExtraEnum.indicators_file ? ['*'] : ['image/png', 'image/jpeg', 'image/jpg']
          "
          :api="
            ruleForm.dimensionExtra == DimensionExtraEnum.indicators_image
              ? fileDetailController.uploadImageUsingPOST
              : fileDetailController.uploadUsingPOST
          "
          v-model:image-url="ruleForm.defaultValue"
        >
          <template #tip>上传内容最大为 2M</template>
        </UploadImg>
        <el-select
          v-else-if="ruleForm.columnType == ColumnTypeEnum.date"
          v-model="ruleForm.defaultValue"
          class-name="m-2"
          placeholder="默认值"
          clearable
        >
          <el-option v-for="option in DateRange" :key="option.value" :label="option.label" :value="option.value" />
        </el-select>

        <el-input v-else-if="useDimensionOptionsResult.columnOptions.value.length < 1" v-model="ruleForm.defaultValue" />

        <el-select v-else v-model="ruleForm.defaultValue" class-name="m-2" placeholder="默认值" clearable>
          <el-option
            v-for="option in useDimensionOptionsResult.columnOptions.value"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-select>
      </el-form-item>

      <el-form-item label="是否可多选" prop="multiSelect">
        <el-checkbox v-model="ruleForm.multiSelect">是否可多选</el-checkbox>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="submitForm(ruleFormRef)"> 提交</el-button>
        <el-button @click="resetForm(ruleFormRef)"> 重置</el-button>
      </el-form-item>
    </el-form>
  </el-dialog>
</template>

<script setup lang="ts" name="addColumn">
import { computed, reactive, ref } from "vue";
import type { FormInstance, FormRules } from "element-plus";
import { ElMessage } from "element-plus";
import {
  ColumnDimensionTypes,
  ColumnOptionsType,
  ColumnType,
  ColumnTypeEnum,
  DateRange,
  DimensionAdvanced,
  DimensionExtraEnum,
  DimensionTypeEnum
} from "@/utils/dict";
import { Link } from "@element-plus/icons-vue";
import { isArray } from "@/utils/is";
import TableColumnForm from "@/views/dwh/tableColumn/components/tableColumnForm.vue";
import UploadImg from "@/components/Upload/Img.vue";
import { fileDetailController, tableColumnController } from "@/api/modules/dwh";
import { useDimensionOptions } from "@/hooks/useDimensionOptions";
import { getColumnOptionsType } from "@/utils/TableColumnUtil";
import { clearObject } from "@/utils";
import { addAdvanced, containAdvanced, removeAdvanced } from "@/utils/dimensionUtil";

const ruleFormRef = ref<FormInstance>();
const ruleForm = reactive({
  columnCode: "",
  columnName: "",
  columnType: "",
  dimensionType: "",
  columnOptions: "",
  defaultValue: "",
  dimensionExtra: "",
  dimensionAdvanced: "",
  multiSelect: false
});

const columnOptionsType = ref<ColumnOptionsType>(ColumnOptionsType.custom);

const isFile = computed(
  () =>
    ruleForm.dimensionType[0] == DimensionTypeEnum.indicators &&
    (ruleForm.dimensionType[1] == DimensionExtraEnum.indicators_image ||
      ruleForm.dimensionType[1] == DimensionExtraEnum.indicators_file)
);
const isAgg = computed(() => ruleForm.dimensionType[0] == DimensionTypeEnum.agg);

const valueCode = computed({
  // getter
  get() {
    if (getColumnOptionsType(ruleForm.columnOptions) != ColumnOptionsType.link_table) return "";
    return JSON.parse(ruleForm.columnOptions).valueCode || "";
  },
  // setter
  set(newValue) {
    let parse = JSON.parse(ruleForm.columnOptions);
    parse.valueCode = newValue;
    ruleForm.columnOptions = JSON.stringify(parse);
  }
});
const emit = defineEmits<{
  submitSuccess: [value: boolean];
}>();
const valueLabel = computed({
  // getter
  get() {
    if (getColumnOptionsType(ruleForm.columnOptions) != ColumnOptionsType.link_table) return "";
    return JSON.parse(ruleForm.columnOptions).valueLabel || "";
  },
  // setter
  set(newValue) {
    let parse = JSON.parse(ruleForm.columnOptions);
    parse.valueLabel = newValue;
    ruleForm.columnOptions = JSON.stringify(parse);
  }
});

const tableInfoId = computed({
  // getter
  get() {
    if (getColumnOptionsType(ruleForm.columnOptions) != ColumnOptionsType.link_table) return "";
    return JSON.parse(ruleForm.columnOptions).tableInfoId || "";
  },
  // setter
  set(newValue) {
    let parse;
    if (getColumnOptionsType(ruleForm.columnOptions) == ColumnOptionsType.link_table) {
      parse = JSON.parse(ruleForm.columnOptions);
    } else {
      parse = {};
    }
    parse.tableInfoId = newValue;
    ruleForm.columnOptions = JSON.stringify(parse);
  }
});

const useDimensionOptionsResult = useDimensionOptions(() => ruleForm.columnOptions);

const dimensionTypeChange = () => {
  ruleForm.defaultValue = "";
  if (ruleForm.dimensionType[0] == DimensionTypeEnum.agg) {
    ruleForm.columnOptions = "";
  }
  if (ruleForm.columnType == ColumnTypeEnum.date) {
    ruleForm.columnOptions = "";
  }
  if (
    ruleForm.dimensionType[1] == DimensionExtraEnum.indicators_image ||
    ruleForm.dimensionType[1] == DimensionExtraEnum.indicators_file ||
    ruleForm.dimensionType[1] == DimensionExtraEnum.indicators_password
  ) {
    ruleForm.columnOptions = "";
  }
  if (ruleForm.dimensionType[1] == DimensionExtraEnum.dimension_primary_key) {
    ruleForm.columnOptions = "";
  }
};

const rules = reactive<FormRules>({
  columnCode: [{ required: true, message: "请输入code" }],
  dimensionType: [{ required: true, message: "类型不能为空" }],
  columnType: [{ required: true, message: "字段类型不能为空" }]
});

const tableColumnFormRef = ref<typeof TableColumnForm>();

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  if (tableColumnFormRef.value && !(await tableColumnFormRef.value.validateForm())) {
    return;
  }
  formEl.validate(async (valid, fields) => {
    if (valid) {
      let row = Object.assign({}, ruleForm);
      if (row.multiSelect) {
        row.dimensionAdvanced = addAdvanced(DimensionAdvanced.multi_select, row.dimensionAdvanced);
      } else {
        row.dimensionAdvanced = removeAdvanced(DimensionAdvanced.multi_select, row.dimensionAdvanced);
      }
      if (isArray(row.dimensionType)) {
        let cacheDimensionType = row.dimensionType;
        row.dimensionType = cacheDimensionType[0];
        row.dimensionExtra = cacheDimensionType[1] ?? "";
      }
      if (row.dimensionType == DimensionTypeEnum.agg) {
        row.columnCode = row.dimensionType + "@" + row.columnCode;
      }
      await tableColumnController.saveOrUpdateUsingPOST(row);
      ElMessage.success("修改成功");
      emit("submitSuccess", true);
      dialogVisible.value = false;
    } else {
      console.log("error submit!", fields);
    }
  });
};

const preview = ref(true);
const dialogVisible = ref(false);

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.resetFields();
};
const show = (row?: { [key: string]: any }, previewed?: boolean) => {
  clearObject(ruleForm);
  if (previewed != undefined) {
    preview.value = previewed;
  }
  Object.assign(ruleForm, row);
  ruleForm.multiSelect = containAdvanced(DimensionAdvanced.multi_select, ruleForm.dimensionAdvanced);
  columnOptionsType.value = getColumnOptionsType(ruleForm.columnOptions);
  dialogVisible.value = true;
};

defineExpose({
  show
});
</script>

<style scoped lang="scss">
.el-form {
  width: 100%;

  .text-center {
    text-align: center;
  }
}
</style>
